package com.zenithmind.document.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.document.mapper.DocumentRatingMapper;
import com.zenithmind.document.pojo.domain.DocumentRating;
import com.zenithmind.document.pojo.dto.DocumentRatingCreateDTO;
import com.zenithmind.document.pojo.dto.DocumentRatingUpdateDTO;
import com.zenithmind.document.pojo.query.DocumentRatingQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentRatingVO;
import com.zenithmind.document.service.DocumentRatingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 文档评分服务实现类
 * 遵循单一职责原则：专注于评分管理
 * 遵循依赖倒置原则：依赖抽象接口而不是具体实现
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DocumentRatingServiceImpl extends ServiceImpl<DocumentRatingMapper, DocumentRating> implements DocumentRatingService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentRatingVO createRating(DocumentRatingCreateDTO createDTO) {
        log.info("创建评分: documentId={}, userId={}, rating={}", 
                createDTO.getDocumentId(), createDTO.getUserId(), createDTO.getRating());
        
        // 检查用户是否已评分
        if (hasUserRated(createDTO.getDocumentId(), createDTO.getUserId())) {
            throw new RuntimeException("用户已对此文档评分");
        }
        
        DocumentRating rating = new DocumentRating();
        BeanUtils.copyProperties(createDTO, rating);
        rating.setCreateTime(LocalDateTime.now());
        rating.setUpdateTime(LocalDateTime.now());
        
        save(rating);
        
        // 同步评分统计
        syncRatingStatistics(createDTO.getDocumentId());
        
        return convertToVO(rating);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRating(String id, DocumentRatingUpdateDTO updateDTO) {
        log.info("更新评分: id={}", id);
        
        DocumentRating rating = getById(id);
        if (rating == null) {
            throw new RuntimeException("评分不存在");
        }
        
        BeanUtils.copyProperties(updateDTO, rating);
        rating.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(rating);
        
        if (result) {
            // 同步评分统计
            syncRatingStatistics(rating.getDocumentId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteRating(String id) {
        log.info("删除评分: id={}", id);
        
        DocumentRating rating = getById(id);
        if (rating == null) {
            return false;
        }
        
        boolean result = removeById(id);
        
        if (result) {
            // 同步评分统计
            syncRatingStatistics(rating.getDocumentId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteRatings(List<String> ids) {
        log.info("批量删除评分: ids={}", ids);
        
        // 获取文档ID用于同步统计
        List<DocumentRating> ratings = listByIds(ids);
        
        boolean result = removeByIds(ids);
        
        if (result) {
            // 同步相关文档的评分统计
            ratings.stream()
                    .map(DocumentRating::getDocumentId)
                    .distinct()
                    .forEach(this::syncRatingStatistics);
        }
        
        return result;
    }

    @Override
    public IPage<DocumentRatingVO> getRatingPage(DocumentRatingQueryDTO queryDTO) {
        log.info("分页查询评分");
        
        Page<DocumentRatingVO> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        
        return baseMapper.selectRatingPageWithDetails(page, queryDTO);
    }

    @Override
    public DocumentRatingVO getRatingDetail(String id) {
        log.info("获取评分详情: id={}", id);
        
        DocumentRating rating = getById(id);
        if (rating == null) {
            throw new RuntimeException("评分不存在");
        }
        
        return convertToVO(rating);
    }

    @Override
    public List<DocumentRatingVO> getDocumentRatings(String documentId, Integer limit) {
        log.info("获取文档评分列表: documentId={}", documentId);
        
        return baseMapper.selectDocumentRatings(documentId, limit);
    }

    @Override
    public List<DocumentRatingVO> getUserRatings(String userId, Integer limit) {
        log.info("获取用户评分列表: userId={}", userId);
        
        return baseMapper.selectUserRatings(userId, limit);
    }

    @Override
    public Double getDocumentAverageRating(String documentId) {
        log.info("获取文档平均评分: documentId={}", documentId);
        
        return baseMapper.selectDocumentAverageRating(documentId);
    }

    @Override
    public Object getDocumentRatingStatistics(String documentId) {
        log.info("获取文档评分统计: documentId={}", documentId);
        
        return baseMapper.selectDocumentRatingStatistics(documentId);
    }

    @Override
    public Boolean hasUserRated(String documentId, String userId) {
        log.info("检查用户是否已评分: documentId={}, userId={}", documentId, userId);
        
        return baseMapper.checkUserRated(documentId, userId);
    }

    @Override
    public DocumentRatingVO getUserDocumentRating(String documentId, String userId) {
        log.info("获取用户对文档的评分: documentId={}, userId={}", documentId, userId);
        
        return baseMapper.selectUserDocumentRating(documentId, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentRatingVO rateDocument(String documentId, String userId, Double rating, String comment) {
        log.info("用户评分文档: documentId={}, userId={}, rating={}", documentId, userId, rating);
        
        // 检查用户是否已评分
        if (hasUserRated(documentId, userId)) {
            throw new RuntimeException("用户已对此文档评分，请使用更新评分功能");
        }
        
        DocumentRating documentRating = DocumentRating.createRating(documentId, userId, rating, comment);
        save(documentRating);
        
        // 同步评分统计
        syncRatingStatistics(documentId);
        
        return convertToVO(documentRating);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUserRating(String documentId, String userId, Double rating, String comment) {
        log.info("更新用户评分: documentId={}, userId={}, rating={}", documentId, userId, rating);
        
        DocumentRating existingRating = baseMapper.selectUserDocumentRatingEntity(documentId, userId);
        if (existingRating == null) {
            throw new RuntimeException("用户尚未对此文档评分");
        }
        
        existingRating.updateRating(rating, comment);
        boolean result = updateById(existingRating);
        
        if (result) {
            // 同步评分统计
            syncRatingStatistics(documentId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelUserRating(String documentId, String userId) {
        log.info("取消用户评分: documentId={}, userId={}", documentId, userId);
        
        boolean result = baseMapper.deleteUserRating(documentId, userId) > 0;
        
        if (result) {
            // 同步评分统计
            syncRatingStatistics(documentId);
        }
        
        return result;
    }

    @Override
    public List<Object> getRatingDistribution(String documentId) {
        log.info("获取评分分布: documentId={}", documentId);
        
        return baseMapper.selectRatingDistribution(documentId);
    }

    @Override
    public List<Object> getTopRatedDocuments(Integer limit) {
        log.info("获取热门评分文档: limit={}", limit);
        
        return baseMapper.selectTopRatedDocuments(limit);
    }

    @Override
    public List<DocumentRatingVO> getLatestRatings(Integer limit) {
        log.info("获取最新评分: limit={}", limit);
        
        return baseMapper.selectLatestRatings(limit);
    }

    @Override
    public List<Object> getRatingTrend(String documentId, Integer days) {
        log.info("获取评分趋势: documentId={}, days={}", documentId, days);
        
        return baseMapper.selectRatingTrend(documentId, days);
    }

    @Override
    public List<DocumentRatingVO> searchRatings(String keyword, Integer limit) {
        log.info("搜索评分: keyword={}, limit={}", keyword, limit);
        
        return baseMapper.searchRatings(keyword, limit);
    }

    @Override
    public List<DocumentRatingVO> getRatingComments(String documentId, Boolean hasComment, Integer limit) {
        log.info("获取评分评论: documentId={}, hasComment={}, limit={}", documentId, hasComment, limit);
        
        return baseMapper.selectRatingComments(documentId, hasComment, limit);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean likeRating(String ratingId, String userId) {
        log.info("点赞评分: ratingId={}, userId={}", ratingId, userId);
        
        return baseMapper.likeRating(ratingId, userId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unlikeRating(String ratingId, String userId) {
        log.info("取消点赞评分: ratingId={}, userId={}", ratingId, userId);
        
        return baseMapper.unlikeRating(ratingId, userId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean reportRating(String ratingId, String userId, String reason) {
        log.info("举报评分: ratingId={}, userId={}, reason={}", ratingId, userId, reason);
        
        return baseMapper.reportRating(ratingId, userId, reason) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean reviewRating(String ratingId, Integer status, String reviewerId) {
        log.info("审核评分: ratingId={}, status={}, reviewerId={}", ratingId, status, reviewerId);
        
        return baseMapper.reviewRating(ratingId, status, reviewerId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchReviewRatings(List<String> ratingIds, Integer status, String reviewerId) {
        log.info("批量审核评分: ratingIds={}, status={}, reviewerId={}", ratingIds, status, reviewerId);
        
        return baseMapper.batchReviewRatings(ratingIds, status, reviewerId) > 0;
    }

    @Override
    public List<DocumentRatingVO> getPendingReviewRatings(Integer limit) {
        log.info("获取待审核评分: limit={}", limit);
        
        return baseMapper.selectPendingReviewRatings(limit);
    }

    @Override
    public Object exportRatings(DocumentRatingQueryDTO queryDTO) {
        log.info("导出评分数据");
        
        return baseMapper.exportRatings(queryDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean syncRatingStatistics(String documentId) {
        log.info("同步评分统计: documentId={}", documentId);
        
        return baseMapper.syncRatingStatistics(documentId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanupSpamRatings() {
        log.info("清理垃圾评分");
        
        return baseMapper.cleanupSpamRatings();
    }

    @Override
    public Object getRatingQualityAnalysis(String documentId) {
        log.info("获取评分质量分析: documentId={}", documentId);
        
        return baseMapper.selectRatingQualityAnalysis(documentId);
    }

    @Override
    public Object getUserRatingBehavior(String userId) {
        log.info("获取用户评分行为分析: userId={}", userId);
        
        return baseMapper.selectUserRatingBehavior(userId);
    }

    @Override
    public List<Object> recommendSimilarRatedDocuments(String documentId, Integer limit) {
        log.info("推荐相似评分文档: documentId={}, limit={}", documentId, limit);
        
        return baseMapper.selectSimilarRatedDocuments(documentId, limit);
    }

    @Override
    public List<Object> getRatingTagStatistics(String documentId) {
        log.info("获取评分标签统计: documentId={}", documentId);
        
        return baseMapper.selectRatingTagStatistics(documentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchImportRatings(List<DocumentRatingCreateDTO> ratings) {
        log.info("批量导入评分: size={}", ratings.size());
        
        List<DocumentRating> ratingEntities = ratings.stream()
                .map(dto -> {
                    DocumentRating rating = new DocumentRating();
                    BeanUtils.copyProperties(dto, rating);
                    rating.setCreateTime(LocalDateTime.now());
                    rating.setUpdateTime(LocalDateTime.now());
                    return rating;
                })
                .toList();
        
        return baseMapper.batchInsertRatings(ratingEntities);
    }

    /**
     * 转换为VO对象
     */
    private DocumentRatingVO convertToVO(DocumentRating rating) {
        DocumentRatingVO vo = new DocumentRatingVO();
        BeanUtils.copyProperties(rating, vo);
        return vo;
    }
}
